<template>
  <div style="border:1px #ccc solid;overflow: auto;width:100%;height:100%;position: absolute;top:0;bottom:0;"
       ref="paperContainerRef" @mousedown="handleStartMovePaper" @mousemove="handleMovePaper"
       @mouseup="handleStopMovePaper">
    <div style="border:1px #ccc solid;position: absolute;overflow: hidden;"
         :style='{width:paperWidth*zoom+"px",height:paperHeight*zoom+"px",}'
         @mousemove="handleMousemove" @mouseup="handleMouseUp" @click="handleClick"
         @drop="handleDrop" @contextmenu="handleRightClick"
         @dragover="allowDrop">
      <div ref="componentContainerRef" style="position: absolute;z-index: 1">
        <!--组件-->
        <DComponentWrapper :components="props.components" :zoom="zoom" v-for="(option,index) of componentList"
                           :option="option"
                           :key="index" @resize="onStartResize" @select="handleSelect"
                           @dragStart="handleComponentDragStart"></DComponentWrapper>
      </div>
      <div style="position: absolute;z-index: 2">
        <!--连接线-->
        <DLink :zoom="zoom" v-for="(option,index) of linkList" :showSelected="false" :option="option" :key="index"
               @select="handleLinkSelect"
               @dragLinePoint="handleDragLinePoint"></DLink>
      </div>
      <div style="position: absolute;z-index: 3">
        <!--组件的锚点-->
        <MComponentAnchorWrapper :zoom="zoom" v-for="(option,index) of componentList" :option="option"
                                 :key="index"
                                 :showAnchor="draggingLinePointIsStart||draggingLinePointIsEnd||drawingLink"></MComponentAnchorWrapper>
      </div>
      <div style="position: absolute;z-index: 4">
        <!--被选中的连接线-->
        <DLink :zoom="zoom" v-for="(option,index) of linkList" :showSelected="true" :option="option" :key="index"
               @select="handleLinkSelect"
               @dragLinePoint="handleDragLinePoint"></DLink>
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
import {nextTick, onMounted, provide, reactive, Ref, ref, shallowRef, watch} from "vue";
import {ComponentAnchor, ComponentOption} from "./ComponentOption.ts";
import DComponentWrapper from "./MComponentWrapper.vue";
import MComponentAnchorWrapper from "./MComponentAnchorWrapper.vue";
import {LinkOption} from "./LinkOption.ts";
import DLink from "./links/link1/MLink.vue";
import {EPoint} from "./EPoint.ts";
import templates from "./templates.ts";
import {v4 as uuidv4} from 'uuid';
import {correctHV, distance2d, flow2int} from "./util.ts";
import EventBus from "./EventBus.ts";
import EventConstant from "./EventConstant";

const eventBus = new EventBus();
provide("eventBus", eventBus);//注册事件总线

const props = defineProps<{
  components: any,
}>();
const emit = defineEmits(['componentSelect', "linkSelect"])
const paperContainerRef: Ref<HTMLElement> = ref(null);
let zoom = ref(1);
let paperWidth = ref(1000);
let paperHeight = ref(1000);
let componentContainerRef = ref(null)
let componentTypeList: Ref<any> = ref([])
for (let key in props.components) {
  let c = props.components[key]
  componentTypeList.value.push({
    label: c.label,
    type: key
  })
}

//页面上的组件列表
let componentList: Array<ComponentOption> = reactive([]);
//先初始化一个组件
// let co: ComponentOption = new ComponentOption("image", null,500, 500, 150, 120)
// co.zIndex = 0
// co.id = "1"
// co.addDefaultAnchors();
// co.option = {
//   url: image_base64["ecu_1.png"]
// }
// componentList.push(co)

//组件模板列表
let templateList: any = reactive(templates);

//正在resize的组件
let resizingComponentOption: ComponentOption | null;
//resize之后要调用的函数
let resizingCallback: Function | null;
//是否在resize
let resizing = false;
//其中的属性的值可以是-1、1、0，表示组件的位置和大小的每一项要往哪个方向变化
let resizingFlag = {xFlag: 0, yFlag: 0, wFlag: 0, hFlag: 0}
//resize操作开始的点坐标
let resizingStartPoint = {top: 0, left: 0}
//resize过程中，浏览器上次触发mousemove的点
let resizingPrePoint = {top: 0, left: 0}
//resize开始的坐标和目标组件的size
let resizingStartGeo = {x: 0, y: 0, w: 0, h: 0}
//被用户选中的组件
let selectedComponentOption: Ref<ComponentOption | null> = ref(null);
//被用户选中的连接线
let selectedLinkOption: Ref<LinkOption | null> = ref(null);
//被选中的组件的配置页面
let selectedComponentOptionView: Ref<any | null> = shallowRef(null);

let linkList: Array<LinkOption> = reactive([]);
onMounted(() => {
  move2center()
})

/**
 * 居中
 */
function move2center() {
  //获得画布的视野属性，进而获得视野宽度和高度
  const paperPos = paperContainerRef.value.getBoundingClientRect()
  paperContainerRef.value.scrollTo(paperWidth.value * zoom.value / 2 - paperPos.width / 2, paperHeight.value * zoom.value / 2 - paperPos.height / 2)
}

function setZoom(z) {
  zoom.value = z
}

function setPagerSize(width: number, height: number) {
  paperWidth.value = width;
  paperHeight.value = height;
}

watch(selectedComponentOption, (nv: any, ov: any) => {
  // refreshIfShow(nse, nsh)
  //选中的组件的位置变化之后，重新计算关联到其上的连接线的起始、结束点位置
  //这里其实只要监控位置和大小就行
  if (nv != null) {
    dealComponentAnchorLink(nv)
  }
}, {deep: true})

// let oldZoomValue = zoom.value;
watch(zoom, (nv, ov) => {
  // oldZoomValue = nv;
  //使用户视窗位置不变
  const paperPos = paperContainerRef.value.getBoundingClientRect()
  let center = {
    x: paperContainerRef.value.scrollLeft + paperPos.width / 2,
    y: paperContainerRef.value.scrollTop + paperPos.height / 2
  }
  let pCenter = {px: center.x / (paperWidth.value * ov), py: center.y / (paperHeight.value * ov)}
  //再反算回去，得到scroll位置
  let newCenter = {x: pCenter.px * (paperWidth.value * nv), y: pCenter.py * (paperHeight.value * nv)}
  let newScrollLeft = newCenter.x - paperPos.width / 2
  let newScrollTop = newCenter.y - paperPos.height / 2
  nextTick(() => {
    paperContainerRef.value.scrollTo(newScrollLeft, newScrollTop);
  })
})

//开始resize操作，记录各变量的值
function onStartResize(callback: Function, _resizingComponentOption: ComponentOption, xFlag: number, yFlag: number, wFlag: number, hFlag: number, startX: number, startY: number, _resizingStartGeo) {
  resizing = true
  resizingFlag = {xFlag, yFlag, wFlag, hFlag};
  resizingCallback = callback
  resizingComponentOption = _resizingComponentOption;
  resizingStartPoint = {left: startX, top: startY}
  resizingPrePoint = {left: startX, top: startY}
  resizingStartGeo = _resizingStartGeo
}

//由鼠标移动事件触发，计算每次鼠标移动导致的组件大小变化
function dealResize(event: MouseEvent) {
  if (resizing && resizingComponentOption != null) {
    let oldResizingPrePoint = resizingPrePoint;
    let newResizingPrePoint = {top: event.screenY, left: event.screenX}
    let deltaY = newResizingPrePoint.top - oldResizingPrePoint.top
    let deltaX = newResizingPrePoint.left - oldResizingPrePoint.left
    deltaY = deltaY / zoom.value
    deltaX = deltaX / zoom.value
    let willWidth = resizingComponentOption.w + resizingFlag.wFlag * deltaX;
    let willHeight = resizingComponentOption.h + resizingFlag.hFlag * deltaY;
    //宽度不能小于0
    if (willWidth >= 0) {
      resizingComponentOption.w = willWidth;
      resizingComponentOption.x = resizingComponentOption.x + resizingFlag.xFlag * deltaX
      resizingPrePoint.left = newResizingPrePoint.left
    } else {//<100
      // resizingComponentOption.w = 100;
      // //需要补偿的宽度
      // let leftWidth = 100 - willWidth;
      // resizingComponentOption.x = resizingComponentOption.x + resizingFlag.xFlag * (deltaX + leftWidth)
      // resizingPrePoint.left = newResizingPrePoint.left + leftWidth
    }
    if (willHeight >= 0) {
      resizingComponentOption.h = willHeight;
      resizingComponentOption.y = resizingComponentOption.y + resizingFlag.yFlag * deltaY
      resizingPrePoint.top = newResizingPrePoint.top
    } else {
      // resizingComponentOption.h = 100;
      // let leftHeight = 100 - willHeight;
      // resizingComponentOption.y = resizingComponentOption.y + resizingFlag.yFlag * (deltaY + leftHeight)
      // resizingPrePoint.top = newResizingPrePoint.top + leftHeight
    }
    if (typeof resizingCallback === 'function') {
      resizingCallback();
    }
    // resizingComponentOption?.figure()
    dealComponentAnchorLink(resizingComponentOption)
  }
}

/**
 * 右键点击
 * @param event
 */
function handleRightClick(event: MouseEvent) {
  event.preventDefault();
  //取消绘制连接线
  if (drawingLink.value) {
    drawingLink.value = false
    drawingLinkOption.value = null
    linkList.pop()
    stopDrawLink();
  }
}

/**
 * 鼠标移动的时候，根据不同的事件状态处理不同的事件
 * @param event
 */
function handleMousemove(event: MouseEvent) {
  if (event.button !== 0) {
    return;
  }
  //转成5的倍数
  let e = {
    clientX: flow2int(event.clientX),
    clientY: flow2int(event.clientY),
    screenX: flow2int(event.screenX),
    screenY: flow2int(event.screenY)
  }
  // eventBus.trigger("panel.mousemove", e);
  dealResize(e)
  dealDrag(e)
  dealDrawLink(e)
  //拖动连接线关键点
  dealDragLinePoint(e)
}

function stopResize() {
  // resizingComponentOption?.figure()
  if (resizing) {
    resizing = false;
    resizingFlag = {xFlag: 0, yFlag: 0, wFlag: 0, hFlag: 0}
    resizingStartPoint = {top: 0, left: 0}
    resizingPrePoint = {top: 0, left: 0}
    resizingCallback = null
    resizingComponentOption = null
    resizingStartGeo = {x: 0, y: 0, w: 0, h: 0}
  }
}

function handleMouseUp(event: MouseEvent) {
  event.preventDefault();
  if (event.button !== 0) {
    return;
  }
  stopResize();
  stopDrag()
  stopDrawLink();
  stopDragLinePoint()
}

function selectLink(option: LinkOption) {
  clearComponentSelected()
  clearLinkSelected()
  selectedLinkOption.value = null
  if (option) {
    option.selected = true;
  }
  selectedLinkOption.value = option
  emit("linkSelect", selectedLinkOption.value)
}

function clearLinkSelected() {

  for (let lo of linkList) {
    lo.selected = false;
  }
  selectedLinkOption.value = null
  emit("linkSelect", selectedLinkOption.value)
}

function selectComponent(option: ComponentOption) {
  clearComponentSelected()
  clearLinkSelected()
  selectedComponentOption.value = null
  selectedComponentOptionView.value = null
  option.selected = true
  selectedComponentOption.value = option
  selectedComponentOptionView.value = props.components[option.type].option
  emit("componentSelect", selectedComponentOption.value, selectedComponentOptionView.value)
}

function clearComponentSelected() {
  for (let comp of componentList) {
    comp.selected = false
  }
  selectedComponentOption.value = null
  selectedComponentOptionView.value = null
  emit("componentSelect", selectedComponentOption.value, selectedComponentOptionView.value)
}

function handleClick() {
  //清除选中的组件
  selectedComponentOption.value = null
  clearComponentSelected()
  clearLinkSelected()
}

function handleSelect(co: ComponentOption) {
  if (resizing) {
    return;
  }
  selectComponent(co)
  //计算zIndex
  let otherComponents = componentList.filter((c: ComponentOption) =>
      c != co
  ).sort((c1: ComponentOption, c2: ComponentOption) => {
    return c1.zIndex - c2.zIndex
  })
  for (let index: number = 0; index < otherComponents.length; index++) {
    let c: ComponentOption = otherComponents[index]
    c.zIndex = index
  }
  co.zIndex = otherComponents.length;
  selectedComponentOptionView.value = props.components[co.type].option
}


let dragging: boolean = false
let draggingComponentOption: ComponentOption | null = null
let draggingCallback: Function | null = null
let draggingPrePoint = {top: 0, left: 0}

//处理组件拖动的逻辑
function handleComponentDragStart(event: MouseEvent, co: ComponentOption, cb: Function) {
  dragging = true
  draggingComponentOption = co
  draggingCallback = cb
  draggingPrePoint = {top: event.clientY, left: event.clientX}
}

function stopDrag() {
  // draggingComponentOption?.figure();
  if (dragging) {
    dragging = false;
    draggingComponentOption = null
    draggingCallback = null
    draggingPrePoint = {top: 0, left: 0}
  }
}

function dealDrag(event: MouseEvent) {
  if (dragging && draggingComponentOption != null) {
    let oldDraggingPoint = draggingPrePoint;
    let newDraggingPoint = {top: event.clientY, left: event.clientX}
    let deltaX = newDraggingPoint.left - oldDraggingPoint.left
    let deltaY = newDraggingPoint.top - oldDraggingPoint.top
    deltaY = deltaY / zoom.value
    deltaX = deltaX / zoom.value
    draggingComponentOption.x += deltaX
    draggingComponentOption.y += deltaY
    draggingPrePoint = newDraggingPoint
    // draggingComponentOption?.figure()
    //找到组件所有锚点关联的link，更新其位置
    dealComponentAnchorLink(draggingComponentOption)
  }
}

/*
 *找到组件所有锚点关联的link，更新其绑定的位置
 */
function dealComponentAnchorLink(targetComponentOption: ComponentOption) {
  for (let anchor of targetComponentOption.anchors) {
    refreshAnchorLink(anchor);
  }
}

function refreshAnchorLink(anchor: ComponentAnchor) {
  for (let link of linkList) {
    if (link.startAnchor === anchor) {
      link.points[0].x = anchor.point.x
      link.points[0].y = anchor.point.y
    }
    if (link.endAnchor === anchor) {
      let length = link.points.length;
      link.points[length - 1].x = anchor.point.x
      link.points[length - 1].y = anchor.point.y
    }
  }
}

function handleDrop(event: DragEvent) {
  if (event && event.dataTransfer) {
    event.preventDefault();
    event.stopPropagation()
    let dataString = event.dataTransfer.getData('data');
    if (!dataString) {
      return;
    }
    let data = JSON.parse(dataString);
    let sourceType = data.sourceType
    if (sourceType === 'component') {
      let targetComponentOption = props.components[data.type];
      if (targetComponentOption) {
        let newCo = targetComponentOption.initOption();
        newCo.x = event.offsetX / zoom.value - data.offsetX
        newCo.y = event.offsetY / zoom.value - data.offsetY
        newCo.zIndex = 1
        componentList.push(newCo)
        selectComponent(newCo)
      }
    }
    if (sourceType === 'template') {
      //创建新的组件实例
      let option = data.option
      let componentType: any = props.components[data.componentType]
      let newCo = new ComponentOption(data.componentType,
          null,
          event.offsetX / zoom.value - data.offsetX,
          event.offsetY / zoom.value - data.offsetY,
          option.w, option.h,
          componentType.getTypeOption())
      newCo.option = {...option.option}
      if (option.anchors && option.anchors.length > 0) {
        for (let an of option.anchors) {
          let anchor: ComponentAnchor = new ComponentAnchor(an.px, an.py, null, newCo.id);
          newCo.anchors.push(anchor)
        }
      }
      newCo.selected = true
      newCo.figure()
      componentList.push(newCo)
      selectComponent(newCo)
    }
  }
}

//不知道有啥用
function allowDrop(event: MouseEvent) {
  event.preventDefault()
  event.stopPropagation()
  // console.log('allow drop')
}

let willDrawingLink = false;
const drawingLink = ref(false);
let drawingLinkComponentOption: ComponentOption | null = null;
let drawingLinkComponentAnchor: ComponentAnchor | null = null;
let drawingLinkOption: Ref<LinkOption | null> = ref(null);

//处理创建连接线的逻辑
function handleDrawLinkStart(option: ComponentOption, anchor: ComponentAnchor, event: MouseEvent) {
  //根据鼠标的位置和锚点的位置判断是否绘制出连接线，如果位置相差不大就不用画
  drawingLinkComponentOption = option;
  drawingLinkComponentAnchor = anchor
  clearLinkSelected()
  let cp = getContainerPosition();
  let distance = distance2d(anchor.point.x, anchor.point.y, event.clientX - cp.left, event.clientY - cp.top)
  if (distance <= 5) {
    willDrawingLink = true
  } else {
    drawLinkStart()
    willDrawingLink = false
    dealDrawLink(event)
  }
}

function drawLinkStart() {
  drawingLink.value = true
  //创建一个link
  let lo = LinkOption.startLinkWithAnchor(drawingLinkComponentAnchor, zoom.value)
  lo.selected = true
  lo.isDraggingPoint = true
  drawingLinkOption.value = lo
  linkList.push(lo)
  selectLink(drawingLinkOption.value)
}

function dealDrawLink(event: MouseEvent) {
  if (willDrawingLink) {
    drawLinkStart()
    willDrawingLink = false
    return;
  }
  if (drawingLink.value && drawingLinkOption.value) {
    let cp = getContainerPosition();
    let eventX = event.clientX - cp.left;
    let eventY = event.clientY - cp.top;
    eventX = eventX / zoom.value
    eventY = eventY / zoom.value
    //如果与一个锚点的距离小于5，主动吸附过去
    let aimAnchor: ComponentAnchor | null = null;
    for (let com of componentList) {
      for (let anchor of com.anchors) {
        let distance = distance2d(eventX, eventY, anchor.point.x, anchor.point.y)
        if (distance < 5) {
          aimAnchor = anchor
          break;
        }
      }
      if (aimAnchor) break;
    }
    //首尾不能是同一个锚点
    if (aimAnchor && aimAnchor != drawingLinkOption.value.startAnchor) {
      drawingLinkOption.value.setLastPoint(aimAnchor.point.x, aimAnchor.point.y);
      drawingLinkOption.value.endAnchor = aimAnchor
    } else {
      //调整水平垂直
      let aimPoint = new EPoint(eventX, eventY)
      drawingLinkOption.value.setLastPointObject(aimPoint);
      correctHV({eventX, eventY}, drawingLinkOption.value, aimPoint)
      // drawingLinkOption.value.setLastPoint(aimPoint.x, aimPoint.y);
      drawingLinkOption.value.endAnchor = null
    }
    eventBus.trigger(EventConstant.PANEL_LINK_LOOKING_FOR_END, {x: eventX, y: eventY}, drawingLinkOption.value)
  }
}

function stopDrawLink() {
  willDrawingLink = false
  if (drawingLink.value) {
    drawingLinkOption.value.isDraggingPoint = false;
    //如果只有一个点，就删掉这个link
    if (drawingLinkOption.value && drawingLinkOption.value.points.length === 1) {
      linkList.splice(linkList.indexOf(drawingLinkOption.value), 1)
    } else {
      selectLink(drawingLinkOption.value)
      eventBus.trigger(EventConstant.PANEL_LINK_ENDED)
    }
    drawingLink.value = false;
    drawingLinkComponentOption = null;
    drawingLinkComponentAnchor = null;
    drawingLinkOption.value = null
  }
}

function getContainerPosition() {
  return componentContainerRef.value.getBoundingClientRect()
}

function handleLinkSelect(linkOption: LinkOption) {
  clearLinkSelected()
  clearComponentSelected()
  selectLink(linkOption);
}

let draggingLinePoint: Ref<boolean> = ref(false);
let draggingLinePointP: EPoint | null = null;
let draggingLinePointOption: Ref<LinkOption | null> = ref(null);
const draggingLinePointIsStart = ref(false);
const draggingLinePointIsEnd = ref(false);

//处理拖动连接线上折点的事件
function handleDragLinePoint(event: MouseEvent, option: LinkOption, point: EPoint, isStart: boolean, isEnd: boolean) {
  draggingLinePoint.value = true
  draggingLinePointOption.value = option
  draggingLinePointP = point;
  draggingLinePointIsStart.value = isStart
  draggingLinePointIsEnd.value = isEnd
  option.isDraggingPoint = true;
}

function dealDragLinePoint(event: MouseEvent) {
  if (draggingLinePoint.value && draggingLinePointP != null) {
    let cp = getContainerPosition();
    let eventX = event.clientX - cp.left
    let eventY = event.clientY - cp.top
    eventX = eventX / zoom.value
    eventY = eventY / zoom.value
    //如果拖动的是开始或结束，检查所有的锚点，如果折点在锚点附近就吸附过去
    if (draggingLinePointIsStart.value || draggingLinePointIsEnd.value) {
      let aimAnchor: ComponentAnchor | null = null;
      for (let com of componentList) {
        for (let anchor of com.anchors) {
          let distance = distance2d(eventX, eventY, anchor.point.x, anchor.point.y)
          if (distance < 5) {
            aimAnchor = anchor
            break;
          }
        }
        if (aimAnchor) break;
      }
      if (aimAnchor) {
        if (draggingLinePointIsStart.value) {
          draggingLinePointOption.value.startAnchor = aimAnchor;
          draggingLinePointP.x = aimAnchor.point.x
          draggingLinePointP.y = aimAnchor.point.y
        }
        if (draggingLinePointIsEnd.value) {
          draggingLinePointP.x = aimAnchor.point.x
          draggingLinePointP.y = aimAnchor.point.y
          draggingLinePointOption.value.endAnchor = aimAnchor;
        }
      } else {
        // draggingLinePointP.x = eventX
        // draggingLinePointP.y = eventY
        // 让线自动水平或垂直
        correctHV({eventX, eventY}, draggingLinePointOption.value, draggingLinePointP)
        if (draggingLinePointIsStart.value) draggingLinePointOption.value.startAnchor = null;
        if (draggingLinePointIsEnd.value) draggingLinePointOption.value.endAnchor = null;

      }
    } else {
      // 让线自动水平或垂直
      // draggingLinePointP.x = eventX
      // draggingLinePointP.y = eventY
      correctHV({eventX, eventY}, draggingLinePointOption.value, draggingLinePointP)
    }
  }
}

function stopDragLinePoint() {
  if (draggingLinePoint.value) {
    selectLink(draggingLinePointOption.value)
    draggingLinePointOption.value.isDraggingPoint = false;
    draggingLinePoint.value = false;
    draggingLinePointP = null;
    draggingLinePointIsStart.value = false;
    draggingLinePointIsEnd.value = false;
    draggingLinePointOption.value = null
  }
}

function deleteComponent(targetComponent: ComponentOption) {
  //清除与此组件关联的link的锚点
  for (let anchor of selectedComponentOption.value.anchors) {
    for (let link of linkList) {
      if (link.startAnchor === anchor) {
        link.startAnchor = null;
      }
      if (link.endAnchor === anchor) {
        link.endAnchor = null;
      }
    }
  }
  let index = componentList.indexOf(targetComponent);
  if (index >= 0) {
    componentList.splice(index, 1);
  }
  selectedComponentOption.value = null
  emit("componentSelect", selectedComponentOption.value)

}


function deleteLink(target: LinkOption) {
  let index = linkList.indexOf(target);
  if (index >= 0) {
    linkList.splice(index, 1);
  }
  selectedLinkOption.value = null
  emit("linkSelect", selectedLinkOption.value)
}

const templateNameDialogVisible = ref(false);
const newTemplateName = ref("")

function handleSaveComponent2Template() {
  //提醒用户输入模板名字
  newTemplateName.value = ""
  templateNameDialogVisible.value = true
}

//把选中的组件保存成模板
function saveComponent2Template() {
  let sco: ComponentOption | null = selectedComponentOption.value
  if (!sco) {
    return;
  }
  newTemplateName.value = newTemplateName.value.trim();
  let nt = {
    componentType: sco.type,
    templateId: uuidv4(),
    name: newTemplateName.value,
    option: {
      w: sco.w,
      h: sco.h,
      type: sco.type,
      anchors: [],
      option: JSON.parse(JSON.stringify(sco.option)),
    }
  };
  for (let anchor of sco.anchors) {
    nt.option.anchors.push({px: anchor.px, py: anchor.py})
  }
  //如果名字重复，直接覆盖同名的
  let has = false;
  for (let index = 0; index < templateList.length; index++) {
    let template = templateList[index];
    if (template.name === nt.name) {
      has = true
      templateList.splice(index, 1, nt);
      break;
    }
  }
  if (!has) {
    templateList.push(nt);
  }
  templateNameDialogVisible.value = false
}

let willStartMovePaper = false;
let movingPaper = false;
let movingPaperStartPos = {x: 0, y: 0}
let movingPaperStartScroll = {left: 0, top: 0}

function handleStartMovePaper(event: MouseEvent) {
  if (event.button !== 2) {
    return;
  }
  willStartMovePaper = true
}

function handleMovePaper(event: MouseEvent) {
  if (willStartMovePaper) {
    const paperPos = paperContainerRef.value.getBoundingClientRect()
    movingPaper = true
    willStartMovePaper = false
    movingPaperStartPos = {x: event.clientX - paperPos.left, y: event.clientY - paperPos.top}
    movingPaperStartScroll = {left: paperContainerRef.value.scrollLeft, top: paperContainerRef.value.scrollTop}
    return;
  }
  if (movingPaper) {
    const paperPos = paperContainerRef.value.getBoundingClientRect()
    let deltaX = event.clientX - paperPos.left - movingPaperStartPos.x;
    let deltaY = event.clientY - paperPos.top - movingPaperStartPos.y;
    let targetX = movingPaperStartScroll.left - deltaX
    let targetY = movingPaperStartScroll.top - deltaY
    paperContainerRef.value.scrollTo(targetX, targetY);
  }
}

function handleStopMovePaper() {
  willStartMovePaper = false
  movingPaper = false;
}

function restore(jsonString: string) {
  let jsonData = JSON.parse(jsonString);
  //清除原来的
  componentList.splice(0, componentList.length)
  linkList.splice(0, linkList.length)

  for (let c of jsonData['componentList']) {
    let co = ComponentOption.fromJson(c);
    componentList.push(co)
  }
  for (let l of jsonData['linkList']) {
    let lo = LinkOption.fromJson(l, componentList);
    linkList.push(lo)
  }
}

//导出成json字符串
function expt(): string {
  let jComponentList = []
  let jLinkList = []
  for (let component of componentList) {
    jComponentList.push(component.toJson())
  }
  for (let linkOption of linkList) {
    jLinkList.push(linkOption.toJson())
  }
  let j = {
    componentList: jComponentList,
    linkList: jLinkList
  }
  return JSON.stringify(j);
}

//给下级组件提供的所有事件
provide("panelEvents", {
  drawLinkStart: handleDrawLinkStart,//开始绘制连接线
})
provide("panelApi", {
  getPanelPosition: getContainerPosition,//获得panel位置
})
provide("panelStatus", {
  drawingLink,//正在创建连接线
  drawingLinkOption,//正在被创建的连接线
  draggingLinePoint,//正在拖动连接线的关键点
  draggingLinePointOption,//正在拖动关键点所属的连接线
  draggingLinePointIsStart,
  draggingLinePointIsEnd,
})
defineExpose({
  move2center,
  setZoom,
  deleteComponent,
  deleteLink,
  setPagerSize,
  componentList,
  linkList,
  expt,
  restore,
})

</script>
